package com.yy.json;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class Utils {

    public static List<FieldSerializer> computeGetters(Class<?> cls, Map<String, Field> fieldMap) {
        Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<>();
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            if (Modifier.isStatic(method.getModifiers())) {
                continue;
            }
            if (method.getReturnType().equals(Void.TYPE)) {
                continue;
            }
            if (method.getParameterTypes().length != 0) {
                continue;
            }
            if (methodName.equals("getClass")) {
                continue;
            }
            String propertyName;
            if (methodName.startsWith("get")) {
                if (methodName.length() < 4) {
                    continue;
                }
                char c3 = methodName.charAt(3);
                propertyName = Character.toLowerCase(c3) + methodName.substring(4);
                Field field = fieldMap.get(propertyName);
                FieldInfo fileInfo = new FieldInfo(propertyName, method, field);
                fieldInfoMap.put(propertyName, fileInfo);
            }


            if (methodName.startsWith("is")) {
                if (methodName.length() < 3) {
                    continue;
                }

                if (method.getReturnType() != Boolean.TYPE &&
                        method.getReturnType() != Boolean.class) {
                    continue;
                }
                char c2 = methodName.charAt(2);
                propertyName = Character.toLowerCase(c2) + methodName.substring(3);
                if (!fieldInfoMap.containsKey(propertyName)) {
                    Field field = fieldMap.get(propertyName);
                    FieldInfo fileInfo = new FieldInfo(propertyName, method, field);
                    fieldInfoMap.put(propertyName, fileInfo);
                }
            }
        }
        //所有的公用属性
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            String propertyName = field.getName();
            if (!fieldInfoMap.containsKey(propertyName)) {
                FieldInfo fieldInfo = new FieldInfo(propertyName, null, field);
                fieldInfoMap.put(propertyName, fieldInfo);
            }
        }

        List<FieldSerializer> fieldSerializers = new ArrayList<>();
        for (FieldInfo fieldInfo : fieldInfoMap.values()) {
            fieldSerializers.add(new FieldSerializer(fieldInfo));
        }
        return fieldSerializers;
    }

    /**
     * 获取所有的属性
     *
     * @param cls
     * @param fieldMap
     * @return
     */
    public static Map<String, Field> parseAllFieldToCache(Class<?> cls,
                                                          Map<String, Field> fieldMap) {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            if (!fieldMap.containsKey(name)) {
                fieldMap.put(name, field);
            }
        }
        if (cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
            parseAllFieldToCache(cls.getSuperclass(), fieldMap);
        }
        return fieldMap;
    }

    public static boolean isBox(Class<?> type) {
        return type == Integer.class ||
                type == Character.class ||
                type == Short.class ||
                type == Long.class ||
                type == Boolean.class ||
                type == Float.class ||
                type == Double.class;
    }

    public static boolean isString(Class<?> type) {
        return CharSequence.class.isAssignableFrom(type);
    }
}
